package net.daum.mail;

import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;

import org.apache.commons.lang.StringUtils;

import com.sun.mail.pop3.POP3Folder;
import com.sun.mail.pop3.POP3Store;

public class POP3Client {

	private static final String PROTOCOL_POP3S = "pop3s";
	private static final String PROTOCOL_POP3 = "pop3";
	
	protected static final String DEFAULT_TIMEOUT = 55 * 1000 + "";
	protected static final String DEFAULT_SOCKET_TIMEOUT = 55 * 1000 + "";
	protected static final String FETCH_SIZE = 1024 * 128 + "";
	protected static final String APPEND_BUFFER_SIZE = 1024 * 512 + "";
	
	protected String host;
	protected String userid;
	protected String password;
	protected String port;
	protected String security;
	protected boolean keepContent;
	
	protected POP3Store store;
	protected Session session;

	public POP3Client(String host, String userid, String password, String port, String security) {
		this(host, userid, password, port, security, true);
	}
	
	public POP3Client(String host, String userid, String password, String port, String security, boolean keepContent) {
		this.host = host;
		this.userid = userid;
		this.password = password;
		this.port = port;
		this.security = security;
		this.keepContent = keepContent;
	}
	
	public void connect() throws MessagingException {
		connect(false);
	}
	
	public void connect(boolean debug) throws MessagingException {
		if (store == null) {
			store = createStore(debug);
		}
		store.connect(host, userid, password);
	}
	
	public void release() {
		try {
			if (store != null) {
				store.close();
			}
		} catch (MessagingException e) {
			// ignore
		} finally {
			store = null;
		}
	}
	
	protected POP3Store createStore() throws NoSuchProviderException {
		return createStore(false);
	}
	
	protected POP3Store createStore(boolean debug) throws NoSuchProviderException {
		boolean isSsl = isSsl();
		String protocol = isSsl? PROTOCOL_POP3S : PROTOCOL_POP3;
		session = createSession(protocol, isSsl, debug);
		session.setDebug(debug);
		return (POP3Store) session.getStore(protocol);
	}
	
	protected Session createSession() {
		boolean isSsl = isSsl();
		String protocol = isSsl? PROTOCOL_POP3S : PROTOCOL_POP3;
		return createSession(protocol, isSsl, false);
	}
	
	protected Session createSession(String protocol, boolean isSsl, boolean debug) {
		Properties props = new Properties();
		if (!StringUtils.isEmpty(port)) {
			props.setProperty("mail." + protocol + ".port", port);
			props.setProperty("mail." + protocol + ".socketFactory.port", port);
		}

		props.setProperty("mail." + protocol + ".ssl.enable", String.valueOf(isSsl));
		props.setProperty("mail." + protocol + ".connectiontimeout", DEFAULT_TIMEOUT);
		props.setProperty("mail." + protocol + ".timeout", DEFAULT_SOCKET_TIMEOUT);
		props.setProperty("mail." + protocol + ".connectionpoolsize", "3");
		props.setProperty("mail." + protocol + ".connectionpool.debug", "false");
		props.setProperty("mail." + protocol + ".fetchsize", FETCH_SIZE);
		props.setProperty("mail." + protocol + ".appendbuffersize", APPEND_BUFFER_SIZE);
	    props.setProperty("mail." + protocol + ".auth", "true");
	    props.setProperty("mail." + protocol + ".keepmessagecontent", String.valueOf(keepContent));
	    props.setProperty("mail." + protocol + ".ssl.trust", "*");
	    props.setProperty("mail.store.protocol", protocol);
	    props.setProperty("mail.debug.auth", String.valueOf(debug));
		
	    return Session.getDefaultInstance(props, null);
	}
	
	protected boolean isSsl() {
		return StringUtils.equals(security, "ssl") || StringUtils.equals(security, "tls");
	}

	public POP3Store getStore() throws NoSuchProviderException {
		if (store == null) {
			store = createStore();
		}
		return store;
	}
	
	public Session getSession() {
		if (session == null) {
			createSession();
		}
		return session;
	}

	public POP3Folder getFolder() throws MessagingException {
		return (POP3Folder) store.getFolder("Inbox");
	}

}
